Laravel 响应准备

public function prepareResponse($request, $response)
{
    if ($response instanceof PsrResponseInterface) {
        $response = (new HttpFoundationFactory)->createResponse($response);
    }
    // 若不是 \Symfony\Component\HttpFoundation\SymfonyResponse 的对象,则构造成此对象
    elseif (! $response instanceof SymfonyResponse) {
        $response = new Response($response);
    }

    return $response->prepare($request);
}

PsrResponseInterface 类型

public function createResponse(ResponseInterface $psrResponse)
{
    $response = new Response(
        $psrResponse->getBody()->__toString(),
        $psrResponse->getStatusCode(),
        $psrResponse->getHeaders()
    );
    $response->setProtocolVersion($psrResponse->getProtocolVersion());

    foreach ($psrResponse->getHeader('Set-Cookie') as $cookie) {
        $response->headers->setCookie($this->createCookie($cookie));
    }

    return $response;
}

本质就是用的 Response 类

Response 构建

public function __construct($content = '', $status = 200, $headers = array())
{
    $this->headers = new ResponseHeaderBag($headers);
    $this->setContent($content);
    $this->setStatusCode($status);
    $this->setProtocolVersion('1.0');

    // Deprecations
    $class = get_class($this);
    if ($this instanceof \PHPUnit_Framework_MockObject_MockObject || $this instanceof \Prophecy\Doubler\DoubleInterface) {
        $class = get_parent_class($class);
    }
    if (isset(self::$deprecationsTriggered[$class])) {
        return;
    }

    self::$deprecationsTriggered[$class] = true;
    foreach (self::$deprecatedMethods as $method) {
        $r = new \ReflectionMethod($class, $method);
        if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
            @trigger_error(sprintf('Extending %s::%s() in %s is deprecated since version 3.2 and won\'t be supported anymore in 4.0 as it will be final.', __CLASS__, $method, $class), E_USER_DEPRECATED);
        }
    }
}
public function setContent($content)
{
    if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable(array($content, '__toString'))) {
        throw new \UnexpectedValueException(sprintf('The Response content must be a string or object implementing __toString(), "%s" given.', gettype($content)));
    }

    $this->content = (string) $content;

    return $this;
}
public function setStatusCode($code, $text = null)
{
    $this->statusCode = $code = (int) $code;
    if ($this->isInvalid()) {
        throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code));
    }

    if (null === $text) {
        $this->statusText = isset(self::$statusTexts[$code]) ? self::$statusTexts[$code] : 'unknown status';

        return $this;
    }

    if (false === $text) {
        $this->statusText = '';

        return $this;
    }

    $this->statusText = $text;

    return $this;
}
public function isInvalid()
{
    return $this->statusCode < 100 || $this->statusCode >= 600;
}
public function setProtocolVersion($version)
{
    $this->version = $version;

    return $this;
}

响应准备

主要是设置响应头

public function prepare(Request $request)
{
    $headers = $this->headers;
    // 信息类
    if ($this->isInformational() || $this->isEmpty()) {
        $this->setContent(null);
        $headers->remove('Content-Type');
        $headers->remove('Content-Length');
    } else {
        if (!$headers->has('Content-Type')) {
            $format = $request->getRequestFormat();
            # static::$formats = array(
            #    'html' => array('text/html', 'application/xhtml+xml'),
            #    'txt' => array('text/plain'),
            #    'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'),
            #    'css' => array('text/css'),
            #    'json' => array('application/json', 'application/x-json'),
            #    'xml' => array('text/xml', 'application/xml', 'application/x-xml'),
            #    'rdf' => array('application/rdf+xml'),
            #    'atom' => array('application/atom+xml'),
            #    'rss' => array('application/rss+xml'),
            #    'form' => array('application/x-www-form-urlencoded'),
            # );
            if (null !== $format && $mimeType = $request->getMimeType($format)) {
                $headers->set('Content-Type', $mimeType);
            }
        }
        // 设置编码格式
        $charset = $this->charset ?: 'UTF-8';
        if (!$headers->has('Content-Type')) {
            $headers->set('Content-Type', 'text/html; charset='.$charset);
        } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) {
            $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset);
        }
        // 若传输时用分块编码,则移除 Content-Length, 因为采用分块编码时可以知道传输何时完成
        if ($headers->has('Transfer-Encoding')) {
            $headers->remove('Content-Length');
        }

        if ($request->isMethod('HEAD')) {
            $length = $headers->get('Content-Length');
            $this->setContent(null);
            if ($length) {
                $headers->set('Content-Length', $length);
            }
        }
    }

    if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) {
        $this->setProtocolVersion('1.1');
    }

    if ('1.0' == $this->getProtocolVersion() && false !== strpos($this->headers->get('Cache-Control'), 'no-cache')) {
        $this->headers->set('pragma', 'no-cache');
        $this->headers->set('expires', -1);
    }

    $this->ensureIEOverSSLCompatibility($request);

    return $this;
}
public function isInformational()
{
    return $this->statusCode >= 100 && $this->statusCode < 200;
}
protected function ensureIEOverSSLCompatibility(Request $request)
{
    if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) {
        if ((int) preg_replace('/(MSIE )(.*?);/', '$2', $match[0]) < 9) {
            $this->headers->remove('Cache-Control');
        }
    }
}

TylerZou
70 声望20 粉丝

I have a dream!